package com.tzy.tzyrpccore.consumer;

import com.tzy.tzyrpccore.annotation.TzyRcpConsumer;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.*;

/**
 * @author caituxinchu
 */
public class ConsumerBootStrap implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    private final Map<String, Object> proxyMap = new HashMap<>();


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void screenConsumerServiceFields() throws IllegalAccessException {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            Object bean = applicationContext.getBean(beanDefinitionName);
            // 获取这个bean中，所有带@TzyrpcConsumer注解的字段
            List<Field> fieldList = findServiceFields(bean.getClass());
            if (Objects.isNull(fieldList) || fieldList.size() == 0) {
                continue;
            }
            for (Field field : fieldList) {
                String canonicalName = field.getType().getCanonicalName();
                Object targetObj = null;
                if (proxyMap.containsKey(canonicalName)) {
                    targetObj = proxyMap.get(canonicalName);
                } else {
                    // 如果map中没有就创建代理对象
                    targetObj = createProxyObject(field.getType());
                    proxyMap.put(canonicalName, targetObj);
                }
                field.setAccessible(true);
                field.set(bean, targetObj);
            }
        }

    }

    /**
     * 创建代理对象
     *
     * @return
     */
    private Object createProxyObject(Class<?> clazz) {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{clazz},
                new TzyRpcConsumerInvocationHandler(clazz.getName()));
    }

    /**
     * 获取所有带@TzyrpcConsumer的字段
     *
     * @param aClass
     * @return
     */
    private List<Field> findServiceFields(Class<?> aClass) {
        List<Field> result = new ArrayList<>();
        while (Objects.nonNull(aClass)) {
            List<Field> fields = Arrays.stream(aClass.getDeclaredFields())
                    .filter(field -> field.isAnnotationPresent(TzyRcpConsumer.class)).toList();
            if (Objects.nonNull(fields) && fields.size() > 0) {
                result.addAll(fields);
            }
            aClass = aClass.getSuperclass();
        }
        return result;
    }

}
